home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Tools 3
/
Amiga Tools 3.iso
/
grafik
/
raytracing
/
rayshade-4.0.6.3
/
inetray
/
lbuffer.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-08-15
|
4KB
|
193 lines
/*======================================================================
L B U F F E R . C
doc: Mon Apr 26 16:11:25 1993
dlm: Mon May 17 10:01:05 1993
(c) 1993 ant@notylia
uE-Info: 66 6 T 0 0 72 2 2 8 ofnI
======================================================================*/
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/time.h>
/*#define DEBUG /* show ops */
/*#define MLIMIT 100 /* memory limit */
#define LBSIZE (1024-sizeof(struct lBlock *)-sizeof(int)) /* block size */
#define LBALLOC() (lBlock *)malloc(sizeof(lBlock)) /* alloc block */
#define FOREVER while(1)
#define IN 0
#define OUT 1
typedef struct lBlock { /* live block */
struct lBlock *next;
int used;
char buf[LBSIZE];
} lBlock;
static lBlock *head;
static void fill(in,statusP) /* fill buffer */
int in,statusP;
{
lBlock *tail;
int nRead,remain,nBlocks=0,maxFd;
fd_set selRead;
head = tail = LBALLOC(); /* alloc 1st */
if (head == NULL) {
fprintf(stderr,"lBuffer malloc() failed\n");
exit(1);
} else nBlocks++;
head->used = 0;
head->next = NULL;
remain = LBSIZE;
#ifdef DEBUG
fprintf(stderr,"Filling lBuffer...\n");
#endif
do { /* build buffer */
FD_ZERO(&selRead); /* detect death */
FD_SET(in,&selRead); maxFd = in;
if (statusP >= 0)
FD_SET(statusP,&selRead);
if (statusP > maxFd)
maxFd = statusP;
if (select(maxFd+1,&selRead,NULL,NULL,NULL) < 0) {
perror("lBuffer select");
exit(1);
}
if ((statusP >= 0) && /* father dead */
FD_ISSET(statusP,&selRead)) {
#ifdef DEBUG
fprintf(stderr,"Exiting due to parent death...\n");
#endif
exit(1);
}
nRead = read(in,&tail->buf[tail->used], /* read block */
remain);
if (nRead < 0) {
perror("lBuffer read");
exit(1);
}
tail->used += nRead;
remain -= nRead;
if (nRead == 0) break; /* eof */
if (tail->buf[tail->used-1] == '\0') {
tail->used--;
break;
}
if (remain == 0) { /* next block */
tail->next = LBALLOC();
if (tail->next == NULL) {
fprintf(stderr,"lBuffer malloc() failed\n");
exit(1);
} else {
nBlocks++;
#ifdef MLIMIT
if (nBlocks > MLIMIT) {
fprintf(stderr,"lBuffer MLIMIT\n");
exit(1);
}
#endif
}
tail = tail->next;
tail->used = 0;
tail->next = NULL;
remain = LBSIZE;
}
} FOREVER;
close(in);
}
static void drain(out) /* drain buffer */
int out;
{
lBlock *cur;
cur = head;
#ifdef DEBUG
fprintf(stderr,"Draining lBuffer...\n");
#endif
do {
if (write(out,cur->buf,cur->used) != cur->used) {
perror("lBuffer write");
exit(1);
}
cur = cur->next;
} while (cur != NULL);
close(out);
}
/*======================================================================*/
static killed() /* killed nicely */
{
exit(0);
}
lPreBuffer(out1,out2) /* buf twice */
int out1[2],out2[2];
{
int pid,statusP[2];
if (pipe(statusP) < 0) { /* status pipe */
perror("lBuffer pipe");
exit(1);
}
if ((pid = fork()) < 0) { /* build proc */
perror("lBuffer fork");
exit(1);
}
if (pid > 0) { /* father continues */
close(statusP[IN]);
close(out1[OUT]);
close(out2[OUT]);
return pid;
}
signal(SIGALRM,SIG_IGN); /* child buffers */
signal(SIGINT,SIG_IGN); /* enable killing */
signal(SIGUSR1,killed);
close(statusP[OUT]);
close(out1[IN]);
close(out2[IN]);
fill(IN,statusP[IN]);
signal(SIGUSR1,SIG_IGN); /* disable killing */
drain(out1[OUT]);
drain(out2[OUT]);
exit(0);
}
lPostBuffer(in,out) /* buf once */
int in,out[2];
{
int pid;
#ifdef DEBUG
fprintf(stderr,"lPostBuffer()\n");
#endif
if ((pid = fork()) < 0) { /* build proc */
perror("lBuffer fork");
exit(1);
}
if (pid > 0) { /* father continues */
close(out[OUT]);
return pid;
}
signal(SIGALRM,SIG_IGN); /* child buffers */
close(out[IN]);
fill(in,-1);
drain(out[OUT]);
#ifdef DEBUG
fprintf(stderr,"lPostBuffer normal exit\n");
#endif
exit(0);
}